package wsi.fusion;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.rygh.core.html.table.HtmlTable;
import org.rygh.core.html.table.TableData;
import org.rygh.core.html.table.TableTuple;
import org.rygh.semantic.model.rdf.Predicate;

import wsi.dataguide.tree.WSXmlLeaf;
import wsi.function.Variable;

public class VariableManager {
	public final static Variable E_INPUT = new Variable("?ei");
	public final static Variable E_CENTER = new Variable("?ec");
	private final static String VAR_E = "?e";
	private final static String VAR_X = "?x";
	private final static String VAR_Y = "?y";

	private final Map<WSXmlLeaf, Variable> varMap = new HashMap<>();
	private final Map<Variable, WSXmlLeaf> varInverseMap = new HashMap<>();

	private final Map<Predicate, Variable> varEntityMap = new HashMap<>();
	private final Map<Variable, Predicate> varEntityInverseMap = new HashMap<>();

	private int varIndex = 1;
	private int varEntityIndex = 1;

	public VariableManager() {

	}

	public Variable get(WSXmlLeaf dg_leaf) {
		return varMap.get(dg_leaf);
	}

	public WSXmlLeaf getLeaf(Variable var) {
		return varInverseMap.get(var);
	}

	public Predicate getPredicate(Variable varEntity) {
		return varEntityInverseMap.get(varEntity);
	}

	public Map<Variable, Predicate> getVarEntityInverseMap() {
		return varEntityInverseMap;
	}

	public Map<Variable, WSXmlLeaf> getVarInverseMap() {
		return varInverseMap;
	}

	public Variable register(WSXmlLeaf dg_leaf, boolean superNode) {
		Variable var;

		if (varMap.containsKey(dg_leaf))
			var = varMap.get(dg_leaf);
		else {
			// System.out.println("new dg_leaf " + dg_leaf + " varIndex "
			// + varIndex);

			var = new Variable((superNode ? VAR_Y : VAR_X) + varIndex);
			varMap.put(dg_leaf, var);
			varInverseMap.put(var, dg_leaf);
			varIndex++;
		}

		return var;
	}

	/**
	 * for now we assume there is one predicate from center node to an entity
	 * variable. this will be extended to longer predicate paths.
	 * 
	 * @param pred
	 * @return
	 */
	public Variable register(Predicate pred) {
		// hard copy
		Predicate _pred = new Predicate(pred);
		Variable var;

		if (varEntityMap.containsKey(_pred))
			var = varEntityMap.get(_pred);
		else {
			// System.out.println("register new pred " + pred + " inv "
			// + pred.isInverse() + ", varEntityIndex " + varEntityIndex
			// + " " + varEntityMap.keySet());

			var = new Variable(VAR_E + varEntityIndex);
			varEntityMap.put(_pred, var);
			varEntityInverseMap.put(var, _pred);
			varEntityIndex++;
		}

		return var;
	}

	public HtmlTable toVariableEntityHtmlTable() {
		TableData data = new TableData();
		TableTuple tuple = new TableTuple();
		tuple.add("Variable", "Predicate");
		data.add(tuple);

		for (Entry<Variable, Predicate> e : varEntityInverseMap.entrySet()) {
			tuple = new TableTuple();
			tuple.add(e.getKey().getValue(), e.getValue().getValue());
			data.add(tuple);
		}

		data.sort(0);

		return new HtmlTable("Variables", data, false);
	}

	public HtmlTable toVariableHtmlTable() {
		TableData data = new TableData();
		TableTuple tuple = new TableTuple();
		tuple.add("Variable", "XPath");
		data.add(tuple);

		for (Entry<Variable, WSXmlLeaf> e : varInverseMap.entrySet()) {
			tuple = new TableTuple();
			tuple.add(e.getKey().getValue(), e.getValue().getXpath().getValue());
			data.add(tuple);
		}

		data.sort(0);

		return new HtmlTable("Variables", data, false);
	}
}
